//
// Author:
//   Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2015 Jb Evain
// Copyright (c) 2008 - 2011 Novell, Inc.
//
// Licensed under the MIT/X11 license.
//

using ILRuntime.Mono.Collections.Generic;
using System;
using System.Text;
using System.Threading;
using MD = ILRuntime.Mono.Cecil.Metadata;

namespace ILRuntime.Mono.Cecil
{

    public sealed class GenericInstanceType : TypeSpecification, IGenericInstance, IGenericContext
    {

        Collection<TypeReference> arguments;

        public bool HasGenericArguments
        {
            get { return !arguments.IsNullOrEmpty(); }
        }

        public Collection<TypeReference> GenericArguments
        {
            get
            {
                if (arguments == null)
                    Interlocked.CompareExchange(ref arguments, new Collection<TypeReference>(), null);

                return arguments;
            }
        }

        public override TypeReference DeclaringType
        {
            get { return ElementType.DeclaringType; }
            set { throw new NotSupportedException(); }
        }

        public override string FullName
        {
            get
            {
                StringBuilder name = new StringBuilder();
                name.Append(base.FullName);
                this.GenericInstanceFullName(name);
                return name.ToString();
            }
        }

        public override bool IsGenericInstance
        {
            get { return true; }
        }

        public override bool ContainsGenericParameter
        {
            get { return this.ContainsGenericParameter() || base.ContainsGenericParameter; }
        }

        IGenericParameterProvider IGenericContext.Type
        {
            get { return ElementType; }
        }

        public GenericInstanceType(TypeReference type)
            : base(type)
        {
            base.IsValueType = type.IsValueType;
            etype = MD.ElementType.GenericInst;
        }

        internal GenericInstanceType(TypeReference type, int arity)
            : this(type)
        {
            arguments = new Collection<TypeReference>(arity);
        }
    }
}
